from dataclasses import asdict, dataclass, field
from pathlib import Path
from typing import Literal


@dataclass
class ESSConfig:
    eta: float = 0.95  # 充放电效率
    init_level: float = 1.2  # 初始电量
    max_level: float = 6.0  # 最大电量
    min_level: float = 0.6  # 最小电量
    aging_coef: float = 0.001  # 老化系数
    max_p: float = 3.0  # 最大充放电功率


@dataclass
class HVACConfig:
    max_p: float = 2  # 最大功率
    min_t: float = 68.0  # 最低温度
    max_t: float = 77.0  #  最高温度
    epsilon: float = 0.7  # 室温惯性系数
    eta: float = 2.5  # 制冷系数
    a: float = 0.14  # 建筑热容系数
    init_indoor_temp: float = 73.4  # 初始室内温度


@dataclass
class EVConfig:
    enable: bool = False  # 是否启用EV组件
    eta: float = 0.95  # 充放电效率
    init_level: float = 45  # 初始电量
    max_level: float = 50  # 最大电量
    min_level: float = 10  # 最小电量
    aging_coef: float = 0.001  # 老化系数
    max_p: float = 8.0  # 最大充放电功率
    v2g: bool = False  # 是否支持V2G


@dataclass
class CarbonEmissionConfig:
    enable: bool = False  # 是否启用碳排放机制组件
    coef: float = 0.872  # 碳排放系数
    quota: float = 3.488  # 碳排放配额
    price: float = 0.06  # 碳排放价格


# 外部数据配置
@dataclass
class ExternalDataConfig:
    solar: str = str(Path(__file__).parent / "assets/solar.csv")
    load: str = str(Path(__file__).parent / "assets/load.csv")
    temp_outdoor: str = str(Path(__file__).parent / "assets/outdoor_temp.csv")
    price: str = str(Path(__file__).parent / "assets/dp_price.csv")
    ev_available: str = str(Path(__file__).parent / "assets/ev_available.csv")
    ev_reduction: str = str(Path(__file__).parent / "assets/ev_reduction.csv")


@dataclass
class DurationConfig:
    train: int = 61  # 训练集天数
    valid: int = 61  # 验证集天数
    test: int = 31  # 测试集天数


@dataclass
class GridConfig:
    price_ratio: float = 0.9  # 卖电/购电价格比例


@dataclass
class HomeEnvConfig:
    # 分组的配置项
    ess: ESSConfig = field(default_factory=ESSConfig)  # 储能系统配置
    hvac: HVACConfig = field(default_factory=HVACConfig)  # 空调配置
    ev: EVConfig = field(default_factory=HVACConfig)  # 电动车配置
    carbon_emission: CarbonEmissionConfig = field(
        default_factory=HVACConfig
    )  # 碳排放配置
    external: ExternalDataConfig = field(default_factory=HVACConfig)  # 外部数据配置
    grid: GridConfig = field(default_factory=HVACConfig)  # 电网配置
    duration: DurationConfig = field(default_factory=HVACConfig)  # 持续时间配置

    # 未分组的配置项
    start_day: int | None = None
    max_days: int | None = None
    _type: Literal["train", "valid", "test"] = "train"
    auto_normalize: bool = False

    def __post_init__(self):
        if self.start_day is None:
            if self._type == "train" or self._type == "valid":
                self.start_day = 0
            else:
                self.start_day = DurationConfig().train
        if self.max_days is None:
            self.max_days = getattr(DurationConfig(), self._type)

    def asdict(self):
        return asdict(self)

    @classmethod
    def from_dict(cls, mapping: dict):
        ins = cls(
            ess=ESSConfig(**mapping.get("ess", {})),
            hvac=HVACConfig(**mapping.get("hvac", {})),
            ev=EVConfig(**mapping.get("ev", {})),
            carbon_emission=CarbonEmissionConfig(**mapping.get("carbon_emission", {})),
            external=ExternalDataConfig(**mapping.get("external_data", {})),
            grid=GridConfig(**mapping.get("grid", {})),
            duration=DurationConfig(**mapping.get("duration", {})),
            start_day=mapping.get("start_day", None),
            max_days=mapping.get("max_days", None),
            _type=mapping.get("_type", "train"),
            auto_normalize=mapping.get("auto_normalize", False),
        )
        return ins
